// 
//  MainWindow.cs
//  
//  Author:
//       BOUTRY Arnaud <lordphoenix@tuxfamily.org>
// 
//  Copyright (c) 2010 BOUTRY Arnaud as LordPhoenix <lordphoenix@tuxfamily.org>
// 
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//  
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Runtime.Remoting;
using System.Threading;
using Gtk;
using Gdk;
using Mono.Unix;
using Notifications;

using swmt.swmtProvider;

namespace swmt
{
	public partial class winCloud : Gtk.Window
	{
		private StatusIcon trayicon;
		private ListStore lstServiceList;
		private ArrayList arlPluginList;
		private string _accountlistfile;
		//private string _optionfilename;
		private Timer _tmr;
		
		private OptionList _options;
		//constants used for options names.
		private const string opt_refresh_delay="refresh_delay";
		private const string opt_show_notification="show_notification"; 
		private const string opt_Hide_on_close ="HideOnClose";
		
		private bool nonotify = true; //Flag used on application start to prevent notification on start.
		
		private void RenderServiceName(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
		{
			WebService selected = (WebService)model.GetValue(iter,0);
			if (selected != null)
				(cell as CellRendererText).Text = selected.servicename;

		}
		private void RenderUnreadCount(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
		{
			WebService selected = (WebService)model.GetValue(iter,0);
			if (selected!=null)
				(cell as CellRendererText).Text =selected.LastCount.ToString();
		}
		private void Close(){
			#region saving account configuration
			int idx = 1;
			FileStream fichier;
			if(!File.Exists(_accountlistfile))
				fichier = File.Open(_accountlistfile,FileMode.Create);
			else
				fichier = File.Open (_accountlistfile, FileMode.Truncate, System.IO.FileAccess.Write);
			StreamWriter w = new StreamWriter (fichier);
			w.BaseStream.Seek (0, SeekOrigin.Begin);
			string confdir = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)+"/swmt/";
			TreeIter iter;
			if(lstServiceList.GetIterFirst(out iter))
				do{
					WebService service =(WebService)lstServiceList.GetValue(iter,0);
					string accountoptionfile = idx.ToString () + "-" + service.servicename + ".conf";
					service.saveconfig (confdir+accountoptionfile);
					string tmpstring = idx.ToString()+"/"+service.pluginfile+"/"+accountoptionfile;
					w.WriteLine (tmpstring);
				}while(lstServiceList.IterNext(ref iter));
			w.Flush ();
			fichier.Flush ();
			fichier.Close ();
			w.Close ();
			#endregion
			#region saving application option
			_options.Save();
			#endregion
			Application.Quit();
		}
		private void RefreshAccount(){
			statusbar1.Push(0,Catalog.GetString("Actualisation en cours…"));
			TreeIter iter;
			Hashtable NotifyCount = new Hashtable();
			if(lstServiceList.GetIterFirst(out iter))
				do{
				WebService service =(WebService)lstServiceList.GetValue(iter,0);
				if(service.connect()){
					int i=service.GetUnreadCount();
					NotifyCount.Add(service.servicename,i);
					}
				}while(lstServiceList.IterNext(ref iter));
			if(!nonotify && _options.getBool(opt_show_notification))
				ShowNotification(NotifyCount);
			statusbar1.Pop(0);
			trvUnreadServices.QueueDraw();
			nonotify = false;
		}
		private void ShowNotification(Hashtable messageinfo){
			Notification alert = new Notification();
			alert.Summary = "SWMT";
			alert.Body = Catalog.GetString("Nouveaux éléments disponibles : ");
			foreach(DictionaryEntry entry in messageinfo){
				string messageline = String.Format("\n\t{0} pour : {1}.",entry.Value.ToString(),entry.Key.ToString());
				alert.Body += messageline;
			}
			alert.Urgency = Urgency.Normal;
			alert.Icon = new Gdk.Pixbuf(null,"swmt.img.swmt.png");
			alert.Show();
		}
		private void onTimerElapsed(object state){
			Gtk.Application.Invoke (delegate {
				this.RefreshAccount();
			});
		}
		protected void onTrayMenu(object sender, EventArgs args){
			Menu traymenu = new Menu();
			ImageMenuItem mnuQuit = new ImageMenuItem(Stock.Quit,null);
			ImageMenuItem mnuRefresh = new ImageMenuItem(Stock.Refresh,null);
			mnuRefresh.Activated += delegate{
				RefreshAccount();
			};
			ImageMenuItem mnuAbout = new ImageMenuItem(Stock.About,null);
			mnuAbout.Activated += OnBtnAboutClicked;
			mnuQuit.Activated += delegate {
				this.Close();
			};
			traymenu.Add(mnuRefresh);
			traymenu.Add(mnuAbout);
			traymenu.Add(mnuQuit);
			traymenu.ShowAll();
			traymenu.Popup();
		}
		public winCloud () : base(Gtk.WindowType.Toplevel)
		{
			Build ();
			arlPluginList = new ArrayList();
			Pixbuf img = new Pixbuf(null,"swmt.img.swmt.png");
			trayicon = new StatusIcon(img);
			trayicon.Visible = true;
			trayicon.Activate += delegate { this.Visible = !this.Visible; };
			trayicon.PopupMenu += onTrayMenu;
			Mono.Unix.Catalog.Init("swmt","");
			#region Graphical elements definition
			TreeViewColumn trcService = new TreeViewColumn();
			trcService.Expand = true;
			trcService.Title = Catalog.GetString("Service");
			CellRendererText celService = new CellRendererText();
			trcService.PackStart(celService,true);
			trcService.SetCellDataFunc(celService,new Gtk.TreeCellDataFunc(RenderServiceName));
			TreeViewColumn trcUnread  = new TreeViewColumn();
			trcUnread.FixedWidth = 20;
			trcUnread.Title = Catalog.GetString("Non lus");
			CellRendererText celUnread = new CellRendererText();
			trcUnread.PackStart(celUnread,true);
			trcUnread.SetCellDataFunc(celUnread,new Gtk.TreeCellDataFunc(RenderUnreadCount));

			trvUnreadServices.AppendColumn(trcService);
			trvUnreadServices.AppendColumn(trcUnread);

			lstServiceList = new ListStore (typeof(WebService));
			trvUnreadServices.Model = lstServiceList;

			#endregion
			#region account list loading.
			string confdir = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)+"/swmt/";
			if (!Directory.Exists(confdir))
				Directory.CreateDirectory(confdir);
			_accountlistfile = confdir+"accounts.list";
			FileStream fichier;
			StreamReader read;
			string optionstring;
			if(File.Exists(_accountlistfile)){
				fichier = File.Open (_accountlistfile, FileMode.Open);
				read = new StreamReader (fichier);
				read.BaseStream.Seek (0, SeekOrigin.Begin);
				while (!read.EndOfStream) {
					optionstring = read.ReadLine();
					if(!optionstring.StartsWith("#")){
						int cpos = optionstring.IndexOf("/");
						int cpos2 = optionstring.IndexOf("/",cpos+1);
						string pluginfile = optionstring.Substring(cpos+1,cpos2-cpos-1);
						string paramfile = optionstring.Substring (cpos2+1, optionstring.Length - cpos2 - 1);
						string filename =GetPluginDir()+pluginfile;
						WebService account = null;
						Assembly ass = Assembly.LoadFrom(filename);
						PluginInfoAttribute[] attrlist = (PluginInfoAttribute[])ass.GetCustomAttributes(typeof(PluginInfoAttribute),true);
						if(attrlist.Length==1){
							string classename = "swmt.swmtProvider."+attrlist[0].ClassName;
							account= (WebService)ass.CreateInstance(classename,true);
							account.loadconfig(confdir+paramfile);
							lstServiceList.AppendValues(account);
						}
					}
				}
				read.Close();
				fichier.Close();
			}

			#endregion
			#region Loading option file
			string _optionfilename;
			_optionfilename = confdir+"options.txt";
			if(File.Exists(_optionfilename)){
				_options = new OptionList(_optionfilename);
			}
			else{
				//If option file doesn't exist set default value for options
				_options = new OptionList();
				_options.set(opt_refresh_delay,10);
				_options.set(opt_show_notification,true);
				_options.set(opt_Hide_on_close,false);
				_options.Save(_optionfilename);
			}
			try {
				int delay = _options.getInt(opt_refresh_delay)*60000;
				_tmr = new Timer(onTimerElapsed,null,0,delay);
				spbRefreshDelay.Value = _options.getInt(opt_refresh_delay);
				ckbNotfy.Active = _options.getBool(opt_show_notification);
				ckbHideOnClose.Active = _options.getBool(opt_Hide_on_close);
			}
			catch(UndefinedOptionException e){
				if(e.OptionName==opt_refresh_delay){
					_options.set(opt_refresh_delay,10);
					_tmr = new Timer(onTimerElapsed,null,0,10*60000);
					spbRefreshDelay.Value = 10;
				}
				if(e.OptionName==opt_show_notification){
					_options.set(opt_show_notification,true);
					ckbNotfy.Active = true;
				}
				if(e.OptionName==opt_Hide_on_close){
					_options.set(opt_Hide_on_close,false);
					ckbHideOnClose.Active = false;
				}
					
			}
			#endregion
		}
		
		/// <summary>
		/// TODO: write a comment.
		/// </summary>
		private static string GetPluginDir ()
		{
			string asslocation=System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			int pos = asslocation.LastIndexOf(System.IO.Path.DirectorySeparatorChar);
			return asslocation.Substring(0,pos)+"/swmt-plugins/";
		}
		protected void OnDeleteEvent (object sender, DeleteEventArgs a)
		{
			a.RetVal = true;
			if(_options.getBool(opt_Hide_on_close))
				this.Hide();
			else
				this.Close();
			
		}
		
		protected virtual void OnBtnAddAccountClicked (object sender, System.EventArgs e)
		{
			Menu mnuadd = new Menu();
			arlPluginList.Clear();
			string rundir = GetPluginDir()+"/";
			foreach(string pluginfilename in Directory.GetFiles(rundir,"*.dll")){
				Assembly ass = Assembly.LoadFrom(pluginfilename);
				PluginInfoAttribute[] attrlist = (PluginInfoAttribute[])ass.GetCustomAttributes(typeof(PluginInfoAttribute),true);
				if(attrlist.Length!=0){
					string _servicename = attrlist[0].ServiceName;
					int idx = arlPluginList.Add(pluginfilename);
					MenuItemData mnuService = new MenuItemData(_servicename,idx);
					mnuService.Activated += NewServiceItemActivated;
					mnuadd.Append(mnuService);
				}
			}
			mnuadd.ShowAll();
			mnuadd.Popup(null,null,null,0,Gtk.Global.CurrentEventTime);
		}
		protected virtual void NewServiceItemActivated(object sender,EventArgs args)
		{
			WebService newservice;
			int idx = (sender as  MenuItemData).index;
			string pluginfile = arlPluginList[idx].ToString();
			Assembly ass = Assembly.LoadFrom(pluginfile);
			PluginInfoAttribute[] attrlist = (PluginInfoAttribute[])ass.GetCustomAttributes(typeof(PluginInfoAttribute),true);
			if(attrlist.Length!=0){
				string ClasseName = "swmt.swmtProvider."+attrlist[0].ClassName;
				newservice = (WebService)ass.CreateInstance(ClasseName,true);
				ResponseType result = newservice.Prompt(false);
				if (result == ResponseType.Ok)
					lstServiceList.AppendValues(newservice);
			}
		}
		protected virtual void OnBtnDeleteAccountClicked (object sender, System.EventArgs e)
		{
			TreeIter iter;
			if (trvUnreadServices.Selection.GetSelected(out iter)){
				WebService service = (WebService)lstServiceList.GetValue(iter,0);
				service.deleteconfigfile();
				lstServiceList.Remove(ref iter);
			}
		}		
		protected virtual void OnBtnRefreshClicked (object sender, System.EventArgs e)
		{
			RefreshAccount();
		}
		protected virtual void OnBtnEditAccountClicked (object sender, System.EventArgs e)
		{
			TreeIter iter;
			if(trvUnreadServices.Selection.GetSelected(out iter)){
				WebService service = (WebService)lstServiceList.GetValue(iter,0);
				service.Prompt(true);
			}
		}
		
		protected virtual void OnSpbRefreshDelayValueChanged (object sender, System.EventArgs e)
		{
			_options.set(opt_refresh_delay,(int)spbRefreshDelay.Value);
			_tmr.Change(0,_options.getInt(opt_refresh_delay)*60000);
		}
		protected virtual void OnCkbNotfyToggled (object sender, System.EventArgs e)
		{
			_options.set(opt_show_notification,ckbNotfy.Active);
		}
		protected virtual void OnCkbHideOnCloseToggled (object sender, System.EventArgs e)
		{
			_options.set(opt_Hide_on_close ,ckbHideOnClose.Active);
		}
		public virtual void OnBtnAboutClicked (object sender, System.EventArgs e)
		{
			AboutDialog dlg = new Gtk.AboutDialog();
			string[] authors = new String[]{"BOUTRY Arnaud <lordphoenix@tuxfamily.org>"};
			dlg.ProgramName ="Social Web Monitor Tool";
			dlg.Logo = new Gdk.Pixbuf(null,"swmt.img.swmt.png");
			dlg.Comments=Catalog.GetString("Surveille vos services web préférés et vous préviens des nouveaux contenus");
			dlg.Version="0.1";
			dlg.Authors = authors;
			string[] artists = new string[]{Catalog.GetString("L'icone principale de SWMT vient de :" +
				" http://www.public-domain-photos.com")};
			dlg.Artists = artists;
			dlg.License=@"This program is free software; you can redistribute it and/or modify 
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
	
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
	
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n";
			dlg.Run();
			dlg.Hide();
		}
		
		
	}
}
	
	

